#include "SessionController.h"
#include <memory>
#include <functional>
#include <iostream>
#include <Windows.h>
#include "UserModel.h"
#include "Utils.h"
#include "SettingModel.h"
#include "CheckWin.h"

#define BIND_CALLBACK(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)

SessionController::SessionController()
{
    m_view = SessionView::getInstance();
    m_model = SessionModel::getInstance();
    m_anlysizeAiActionCallback[SessionAction::ACTION_OUTPUT] = BIND_CALLBACK(SessionController::anlysizeAiOutput, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_GANG] = BIND_CALLBACK(SessionController::anlysizeAiGang, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_PENG] = BIND_CALLBACK(SessionController::anlysizeAiPeng, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_CHI] = BIND_CALLBACK(SessionController::anlysizeAiChi, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_ANGANG] = BIND_CALLBACK(SessionController::anlysizeAiAnGang, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_XUGANG] = BIND_CALLBACK(SessionController::anlysizeAiXuGang, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_HU] = BIND_CALLBACK(SessionController::anlysizeAiHu, this);
    m_anlysizeAiActionCallback[SessionAction::ACTION_ZIMO] = BIND_CALLBACK(SessionController::anlysizeAiZimo, this);

    m_playerActionCallback[SessionAction::ACTION_OUTPUT] = BIND_CALLBACK(SessionController::playerOutputChess, this);
    m_playerActionCallback[SessionAction::ACTION_GANG] = BIND_CALLBACK(SessionController::playerGangChess, this);
    m_playerActionCallback[SessionAction::ACTION_PENG] = BIND_CALLBACK(SessionController::playerPengChess, this);
    m_playerActionCallback[SessionAction::ACTION_CHI] = BIND_CALLBACK(SessionController::playerChiChess, this);
    m_playerActionCallback[SessionAction::ACTION_ANGANG] = BIND_CALLBACK(SessionController::playerAnGangChess, this);
    m_playerActionCallback[SessionAction::ACTION_XUGANG] = BIND_CALLBACK(SessionController::playerXuGangChess, this);
    m_playerActionCallback[SessionAction::ACTION_HU] = BIND_CALLBACK(SessionController::playerHuChess, this);
    m_playerActionCallback[SessionAction::ACTION_ZIMO] = BIND_CALLBACK(SessionController::playerZimoChess, this);
}
SessionController::~SessionController()
{
}

void SessionController::ready2Game()
{
    if (m_model->getSessionCunt() == 0)
    {
        m_view->showSitPostionLayer();
    }

    startSession();
    startDispatch();
}

void SessionController::userSitPostion(Postion ps)
{
    m_model->setUserPlayer(ps);
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; i++)
    {
        auto player = m_model->getSessionPlayerByPs(static_cast<Postion>(i));
        m_view->showPlayerInfo(player, getSitPostionByPs(player.postion));
    }
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; ++i)
    {
        SessionPlayer player = {};
        if (i == ps)
        {
            auto userInfo = UserModel::getInstance()->getUserInfo();
            player.id = userInfo.id;
            player.name = userInfo.name;
            player.ico = userInfo.ico;
            player.postion = ps;
            player.role = RoleType::CLIENT;
            player.score = 0;
            m_model->addSessionPlayer(ps, player);
        }
        else
        {
            player.id = std::string("bot") + std::to_string(i);
            player.name = std::string("bot") + std::to_string(i);
            player.ico = std::string("bot") + std::to_string(i);
            player.postion = (Postion)i;
            player.role = RoleType::CLIENT;
            player.score = 0;
            m_model->addSessionPlayer(player.postion, player);
        }
    }

    m_model->setUserPlayer(ps);
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; i++)
    {
        auto player = m_model->getSessionPlayerByPs(static_cast<Postion>(i));
        m_view->showPlayerInfo(player, getSitPostionByPs(player.postion));
    }

    short maxDiceCunt = 0;
    Postion hostPs = Postion::DEFAULT;
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; ++i)
    {
        short diceCunt1 = Utils::shakeDiceResult();
        short diceCunt2 = Utils::shakeDiceResult();
        short diceCunt = diceCunt1 + diceCunt2;
        if (maxDiceCunt < diceCunt)
        {
            maxDiceCunt = diceCunt;
            hostPs = Postion(i);
        }
        auto player = m_model->getSessionPlayerByPs(Postion(i));
        m_view->shakeDiceAnimation(getSitPostionByPs(player.postion), player, diceCunt1, diceCunt2);
    }

    m_model->setHostPlayer(hostPs);
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; i++)
    {
        auto player = m_model->getSessionPlayerByPs(static_cast<Postion>(i));
        m_view->showPlayerInfo(player, getSitPostionByPs(player.postion));
    }
}

void SessionController::playerAction(const OutcutActionInfo& outputAction)
{
    std::map<short, PlayerActionCallback>::iterator iterFind = m_playerActionCallback.find(outputAction.action);
    if (iterFind != m_playerActionCallback.end())
    {
        iterFind->second(outputAction);
    }
}

void SessionController::playerOutputChess(const OutcutActionInfo& outputAction)
{
    m_model->removePlayerChess(outputAction.activePsn, outputAction.outputChess);
    m_view->showCurOutputChess(getSitPostionByPs(outputAction.activePsn), outputAction.outputChess);

    SessionAction resultCs = SessionAction::ACTION_DISPATH;
    Postion resultPs = outputAction.activePsn;
    Postion tmpPostion = outputAction.activePsn;
    std::vector<KindChess> resultWeaveChess;
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE - 1; ++i)
    {
        tmpPostion = Utils::getNextDispatchPostion(tmpPostion);
        auto tmpHandChess = m_model->getHandleChessByPs(tmpPostion);
        std::vector<KindChess> tmpKindChess;
        SessionAction tmpStatus = checkOutputChess2Action(tmpPostion, outputAction.activePsn, tmpHandChess, outputAction.outputChess, tmpKindChess);
        if (tmpStatus > resultCs)
        {
            resultPs = tmpPostion;
            resultCs = tmpStatus;
            resultWeaveChess.swap(tmpKindChess);
        }
        tmpKindChess.clear();
    }

    if (resultCs == SessionAction::ACTION_DISPATH)
    {
        updateChess2NextPsPlayer(outputAction.activePsn, outputAction.outputChess);
        return;
    }

    // ACTION
    SessionActionInfo sessoinActionInfo = {};
    sessoinActionInfo.action = resultCs;
    sessoinActionInfo.sitPsn = getSitPostionByPs(resultPs);
    sessoinActionInfo.activePsn = resultPs;
    sessoinActionInfo.currentPsn = m_model->getTurnerPostion();
    sessoinActionInfo.handChess = m_model->getHandleChessByPs(resultPs);
    sessoinActionInfo.handWeaveChess = m_model->getWeaveChessByPs(resultPs);
    sessoinActionInfo.outputChess = outputAction.outputChess;
    sessoinActionInfo.tmpWeaveChess = resultWeaveChess;
    sessoinActionInfo.sessionPlayer = m_model->getSessionPlayerByPs(resultPs);
    m_view->showSessionAction(sessoinActionInfo);
}

void SessionController::playerGangChess(const OutcutActionInfo& outputAction)
{
    //0 cancel, 1 gang, 2 peng
    auto curTurner = m_model->getTurnerPostion();
    m_model->removePlayerChess(curTurner, outputAction.outputChess);

    if (outputAction.action)
    {
        m_view->showWeaveChessAnimation(getSitPostionByPs(outputAction.activePsn), outputAction.tmpWeaveChess);

        m_model->addWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);
        m_model->removePlayerChessByWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);

        Chess newChess;
        if (!m_model->dispatchGangChess(newChess))
        {
            // TODO
            m_view->showGameOverLayer(getSitPostionByPs(outputAction.activePsn), SessionAction::ACTION_LIUJU);
            return;
        }
        m_model->addPlayerChess(outputAction.activePsn, newChess);

        m_model->setTurnerPostion(outputAction.activePsn);
        checkHandChessAfterDispath();
    }
    else
    {
        updateChess2NextPsPlayer(curTurner, outputAction.outputChess);
        /* KindChess tmpPengWeave = tmpWeaveChess;
         for (auto bg = tmpPengWeave.item.begin();bg != tmpPengWeave.item.end(); ++bg)
         {
             if (*bg == outputChess)
             {
                 tmpPengWeave.item.erase(bg);
             }
         }
         tmpPengWeave.type = ChessStatus::PENG;

         m_view->showWeaveChessAnimation(getSitPostionByPs(activePsn), tmpWeaveChess);

         m_model->addWeaveChess(activePsn, tmpPengWeave);
         m_model->removePlayerChessByWeaveChess(activePsn, tmpPengWeave);

         m_model->setTurnerPostion(activePsn);
         checkHandChessAfterDispath();*/
    }
}

void SessionController::playerPengChess(const OutcutActionInfo& outputAction)
{
    //false cancel, true peng
    auto curTurner = m_model->getTurnerPostion();
    m_model->removePlayerChess(curTurner, outputAction.outputChess);
    if (outputAction.action)
    {
        m_view->showWeaveChessAnimation(getSitPostionByPs(outputAction.activePsn), outputAction.tmpWeaveChess);
        m_model->addWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);
        m_model->removePlayerChessByWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);
        m_model->setTurnerPostion(outputAction.activePsn);
        checkHandChessAfterDispath();
    }
    else
    {
        updateChess2NextPsPlayer(curTurner, outputAction.outputChess);
    }
}

void SessionController::playerChiChess(const OutcutActionInfo& outputAction)
{
    auto curTurner = m_model->getTurnerPostion();
    m_model->removePlayerChess(curTurner, outputAction.outputChess);

    if (outputAction.action)
    {
        m_view->showWeaveChessAnimation(getSitPostionByPs(outputAction.activePsn), outputAction.tmpWeaveChess);
        m_model->addWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);
        m_model->removePlayerChessByWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);
        m_model->setTurnerPostion(outputAction.activePsn);
        checkHandChessAfterDispath();
    }
    else
    {
        updateChess2NextPsPlayer(curTurner, outputAction.outputChess);
    }
}

void SessionController::playerAnGangChess(const OutcutActionInfo& outputAction)
{
    if (outputAction.action)
    {
        m_view->showWeaveChessAnimation(getSitPostionByPs(outputAction.activePsn), outputAction.tmpWeaveChess);
        m_model->addWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);
        m_model->removePlayerChessByWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);

        Chess newChess;
        if (!m_model->dispatchGangChess(newChess))
        {
            // TODO
            m_view->showGameOverLayer(getSitPostionByPs(outputAction.activePsn), SessionAction::ACTION_LIUJU);
            return;
        }
        m_model->addPlayerChess(outputAction.activePsn, newChess);

        m_model->setTurnerPostion(outputAction.activePsn);
        checkHandChessAfterDispath();
    }
    else
    {
        /*auto handChess = m_model->getHandleChessByPs(activePsn);
        auto handWeaveChess = m_model->getWeaveChessByPs(activePsn);
        m_view->showSessionAction(getSitPostionByPs(activePsn),
            SessionAction::ACTION_OUTPUT, activePsn, handChess, Chess(), std::vector<KindChess>());*/
    }
}

void SessionController::playerXuGangChess(const OutcutActionInfo& outputAction)
{
    if (outputAction.action)
    {
        m_view->showWeaveChessAnimation(getSitPostionByPs(outputAction.activePsn), outputAction.tmpWeaveChess);
        m_model->updateWeave2XuGang(outputAction.activePsn, *outputAction.tmpWeaveChess.item.rbegin());
        m_model->removePlayerChessByWeaveChess(outputAction.activePsn, outputAction.tmpWeaveChess);

        Chess newChess;
        if (!m_model->dispatchGangChess(newChess))
        {
            // TODO
            m_view->showGameOverLayer(getSitPostionByPs(outputAction.activePsn), SessionAction::ACTION_LIUJU);
            return;
        }
        m_model->addPlayerChess(outputAction.activePsn, newChess);

        m_model->setTurnerPostion(outputAction.activePsn);
        checkHandChessAfterDispath();
    }
    else
    {
        /*auto handChess = m_model->getHandleChessByPs(activePsn);
        auto handWeaveChess = m_model->getWeaveChessByPs(activePsn);
        m_view->showSessionAction(getSitPostionByPs(activePsn),
            SessionAction::ACTION_OUTPUT, activePsn, handChess, Chess(), std::vector<KindChess>());*/
    }
}

void SessionController::playerHuChess(const OutcutActionInfo& outputAction)
{
    m_view->showGameOverLayer(getSitPostionByPs(outputAction.activePsn), SessionAction::ACTION_HU);

    auto actionSitPs = getSitPostionByPs(outputAction.activePsn);
    auto actionHandChess = m_model->getHandleChessByPs(outputAction.activePsn);
    auto actionWeaveChess = m_model->getWeaveChessByPs(outputAction.activePsn);
    // m_view->showHandChess(actionSitPs, actionHandChess, actionWeaveChess);
}

void SessionController::playerZimoChess(const OutcutActionInfo& outputAction)
{
    m_view->showGameOverLayer(getSitPostionByPs(outputAction.activePsn), SessionAction::ACTION_ZIMO);

    auto actionSitPs = getSitPostionByPs(outputAction.activePsn);
    auto actionHandChess = m_model->getHandleChessByPs(outputAction.activePsn);
    auto actionWeaveChess = m_model->getWeaveChessByPs(outputAction.activePsn);
    // m_view->showHandChess(actionSitPs, actionHandChess, actionWeaveChess);
}

const OutcutActionInfo SessionController::anlysizeAi(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_OUTPUT;
    outputActionInfo.activePsn = sessionActionInfo.activePsn;
    outputActionInfo.currentPsn = sessionActionInfo.currentPsn;

    std::map<short, AnlysizeCallback>::iterator iterFind = m_anlysizeAiActionCallback.find(sessionActionInfo.action);
    if (iterFind == m_anlysizeAiActionCallback.end())
    {
        return outputActionInfo;
    }
    auto outputResult = iterFind->second(sessionActionInfo);
    outputActionInfo.action = outputResult.action;
    outputActionInfo.outputChess = outputResult.outputChess;
    outputActionInfo.tmpWeaveChess = outputResult.tmpWeaveChess;

    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiOutput(const SessionActionInfo& sessionActionInfo)
{
    // 1 .check ting
    // 1
    // 2
    // 3
    // 4
    // 5
    // 6
    // 7
    // 8
    // 9
    // 10
    // 11
    // 12
    // 13
    // 15
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_OUTPUT;
    outputActionInfo.outputChess = sessionActionInfo.handChess.at(0);
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiGang(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_GANG;
    outputActionInfo.tmpWeaveChess = sessionActionInfo.tmpWeaveChess.at(0);
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiPeng(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_PENG;
    outputActionInfo.tmpWeaveChess = sessionActionInfo.tmpWeaveChess.at(0);
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiChi(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_CHI;
    outputActionInfo.tmpWeaveChess = sessionActionInfo.tmpWeaveChess.at(0);
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiAnGang(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_ANGANG;
    outputActionInfo.tmpWeaveChess = sessionActionInfo.tmpWeaveChess.at(0);
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiXuGang(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_XUGANG;
    outputActionInfo.tmpWeaveChess = sessionActionInfo.tmpWeaveChess.at(0);
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiHu(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_HU;
    return outputActionInfo;
}

const OutcutActionInfo SessionController::anlysizeAiZimo(const SessionActionInfo& sessionActionInfo)
{
    OutcutActionInfo outputActionInfo = {};
    outputActionInfo.action = SessionAction::ACTION_ZIMO;
    return outputActionInfo;
}

void SessionController::startSession()
{
    auto conf = SettingModel::getInstance()->getSettingConf();

    m_model->shuffleChess(conf.SessionType);

    m_view->shuffleAnimation();

    auto hostPlayer = m_model->getHostPlayerPs();

    short hostDiceCunt1 = Utils::shakeDiceResult();
    short hostDiceCunt2 = Utils::shakeDiceResult();

    Postion startPostion = Utils::getNextPlayerPsByDice(hostPlayer.postion, hostDiceCunt1 + hostDiceCunt2);
    auto shakeDicePlayer = m_model->getSessionPlayerByPs(startPostion);
    short diceCunt1 = Utils::shakeDiceResult();
    short diceCunt2 = Utils::shakeDiceResult();

    short startDiceCunt = (diceCunt1 + diceCunt2) * 2;

    ShowOffsetPair result[SessionEnum::MAX_PLAYER_SIZE] = {};
    Utils::getChessShowOffset(result, conf.SessionType, startPostion, startDiceCunt);
    m_model->setShowOffsetPair(result);
    auto mainPlayer = m_model->getUserPlayerPs();
    short dispatchOffset = m_model->getDispatchOffset();
    short gangOffset = m_model->getGangOffset();
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; i++)
    {
        auto sitPsn = getSitPostionByPs(static_cast<Postion>(i));
        auto resultPair = result[i];
        m_view->showShuffleChess(-1, -1, sitPsn, resultPair);
    }
    m_view->shakeDiceAnimation(getSitPostionByPs(hostPlayer.postion), hostPlayer, hostDiceCunt1, hostDiceCunt2);
    m_view->shakeDiceAnimation(getSitPostionByPs(shakeDicePlayer.postion), shakeDicePlayer, diceCunt1, diceCunt2);
}

void SessionController::startDispatch()
{
    auto hostPlayer = m_model->getHostPlayerPs();
    Postion nextPs1 = Utils::getNextDispatchPostion(hostPlayer.postion);
    Postion nextPs2 = Utils::getNextDispatchPostion(nextPs1);
    Postion nextPs3 = Utils::getNextDispatchPostion(nextPs2);
    for (size_t i = 0; i < 3; i++)
    {
        disptchStartChess2Ps(hostPlayer.postion);

        disptchStartChess2Ps(nextPs1);

        disptchStartChess2Ps(nextPs2);

        disptchStartChess2Ps(nextPs3);
    }

    disptchJumpChess2Ps(hostPlayer.postion);
    disptchJumpChess2Ps(nextPs1);
    disptchJumpChess2Ps(nextPs2);
    disptchJumpChess2Ps(nextPs3);
    disptchJumpChess2Ps(hostPlayer.postion);

    auto hostUser = m_model->getHostPlayerPs();
    m_model->sortPlayerChess(hostUser.postion);
    auto hosthandChess = m_model->getHandleChessByPs(hostUser.postion);
    m_view->showJumpChessAnimation(getSitPostionByPs(hostUser.postion), hosthandChess, true);

    Postion tmpPostion = hostUser.postion;
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE - 1; ++i)
    {
        tmpPostion = Utils::getNextDispatchPostion(tmpPostion);
        m_model->sortPlayerChess(tmpPostion);
        auto tmphandChess = m_model->getHandleChessByPs(tmpPostion);
        m_view->showJumpChessAnimation(getSitPostionByPs(tmpPostion), tmphandChess, false);
    }

    m_model->setTurnerPostion(hostPlayer.postion);
    checkHandChessAfterDispath();
}

void SessionController::disptchStartChess2Ps(Postion ps)
{
    size_t startOffset = m_model->getDispatchOffset();
    for (size_t i = 0; i < 4; i++)
    {
        Chess newChess = {};
        if (!m_model->dispatchChess(newChess))
        {
            return;
        }
        m_model->addPlayerChess(ps, newChess);
    }
    size_t endOffset = m_model->getDispatchOffset();
    auto shuffleChess = m_model->getShuffleChess();

    short dispatchOffset = m_model->getDispatchOffset();
    short gangOffset = m_model->getGangOffset();
    const ShowOffsetPair *result = m_model->getShowOffsetPair();
    for (short i = 0; i < SessionEnum::MAX_PLAYER_SIZE; i++)
    {
        m_view->showShuffleChess(dispatchOffset, gangOffset, getSitPostionByPs(static_cast<Postion>(i)), result[i]);
    }
    auto handChess = m_model->getHandleChessByPs(ps);
    m_view->showAllHandChess(getSitPostionByPs(ps), handChess, std::vector<KindChess>());
}

void SessionController::disptchJumpChess2Ps(Postion ps)
{
    Chess newChess = {};
    if (!m_model->dispatchChess(newChess))
    {
        return;
    }
    m_model->addPlayerChess(ps, newChess);
}

void SessionController::checkHandChessAfterDispath()
{
    SessionAction sessionAction = {};
    SessionActionInfo sessoinActionInfo = {};
    sessoinActionInfo.activePsn = m_model->getTurnerPostion();
    sessoinActionInfo.currentPsn = m_model->getTurnerPostion();
    sessoinActionInfo.handChess = m_model->getHandleChessByPs(sessoinActionInfo.activePsn);
    sessoinActionInfo.handWeaveChess = m_model->getWeaveChessByPs(sessoinActionInfo.activePsn);

    sessoinActionInfo.action = checkHandChess(sessoinActionInfo.handChess, sessoinActionInfo.handWeaveChess, sessoinActionInfo.tmpWeaveChess);
    sessoinActionInfo.sitPsn = getSitPostionByPs(sessoinActionInfo.activePsn);
    sessoinActionInfo.sessionPlayer = m_model->getSessionPlayerByPs(sessoinActionInfo.activePsn);
    m_view->showSessionAction(sessoinActionInfo);
}

void SessionController::updateChess2NextPsPlayer(Postion activePsn, const Chess& chess)
{
    auto actionSitPs = getSitPostionByPs(activePsn);
    m_model->addOutputChess(activePsn, chess);
    auto actionOutputChess = m_model->getOutputChessByPs(activePsn);
    m_view->showAllOutputChessAnimation(actionSitPs, actionOutputChess);

    m_model->sortPlayerChess(activePsn);
    auto actionHandChess = m_model->getHandleChessByPs(activePsn);
    auto actionWeaveChess = m_model->getWeaveChessByPs(activePsn);


    // next
    auto nextPs = Utils::getNextDispatchPostion(activePsn);
    Chess newChess;
    if (!m_model->dispatchChess(newChess))
    {
        // TODO
        m_view->showGameOverLayer(getSitPostionByPs(activePsn), SessionAction::ACTION_LIUJU);
        return;
    }

    m_model->addPlayerChess(nextPs, newChess);
    m_model->setTurnerPostion(nextPs);

    checkHandChessAfterDispath();
}

SessionAction SessionController::checkHandChess(const std::vector<Chess>& chessVec, const std::vector<KindChess>& handWeaveChess, std::vector<KindChess>& weaveResult)
{
    if (checkHandChessZimo(chessVec, weaveResult))
    {
        return SessionAction::ACTION_ZIMO;
    }

    if (checkHandChessAnGang(chessVec, weaveResult))
    {
        return SessionAction::ACTION_ANGANG;
    }

    if (checkHandChessXuGang(chessVec, handWeaveChess, weaveResult))
    {
        return SessionAction::ACTION_XUGANG;
    }

    return SessionAction::ACTION_OUTPUT;
}

bool SessionController::checkHandChessAnGang(const std::vector<Chess>& chessVec, std::vector<KindChess>& weaveResult)
{
    weaveResult.clear();
    std::vector<Chess> gangChessVec[1024] = {};
    for (size_t i = 0; i < chessVec.size(); i++)
    {
        gangChessVec[chessVec.at(i).getTypeIdentify()].push_back(chessVec.at(i));
    }

    for (short i = 0; i < 1024; i++)
    {
        if (gangChessVec[i].size() == 4)
        {
            KindChess gangWeaveChess = {};
            gangWeaveChess.type = ChessStatus::ANGANG;
            gangWeaveChess.item.swap(gangChessVec[i]);
            weaveResult.push_back(gangWeaveChess);
        }
        else
        {
            gangChessVec[i].clear();
        }
    }
    return (!weaveResult.empty());
}

bool SessionController::checkHandChessXuGang(const std::vector<Chess>& chessVec, const std::vector<KindChess>& handWeaveChess, std::vector<KindChess>& weaveResult)
{
    weaveResult.clear();
    for (size_t j = 0; j < handWeaveChess.size(); j++)
    {
        if (handWeaveChess.at(j).type == ChessStatus::PENG)
        {
            auto itFind = std::find(chessVec.begin(), chessVec.end(), handWeaveChess.at(j).item.at(0));
            if (itFind != chessVec.end())
            {
                KindChess xugangWeaveChess;
                xugangWeaveChess.type = ChessStatus::XUGANG;
                xugangWeaveChess.item = handWeaveChess.at(j).item;
                xugangWeaveChess.item.push_back(Chess(*itFind));
                weaveResult.push_back(xugangWeaveChess);
            }
        }
    }
    return (!weaveResult.empty());
}

bool SessionController::checkHandChessZimo(const std::vector<Chess>& chessVec, std::vector<KindChess>& weaveResult)
{
    CheckWin checkWind(chessVec);
    return checkWind.analyseChess2Win(weaveResult);
}

SessionAction SessionController::checkOutputChess2Action(Postion currentPs, Postion outputPs, const std::vector<Chess>& chessVec, const Chess& chess, std::vector<KindChess>& kindResult)
{
    kindResult.clear();
    if (checkOutputChessHu(chessVec, chess, kindResult))
    {
        return SessionAction::ACTION_HU;
    }

    kindResult.clear();
    if (checkOutputChessGang(chessVec, chess, kindResult))
    {
        return SessionAction::ACTION_GANG;
    }

    kindResult.clear();
    if (checkOutputChessPeng(chessVec, chess, kindResult))
    {
        return SessionAction::ACTION_PENG;
    }

    kindResult.clear();
    if (checkOutputChessChi(currentPs, outputPs, chessVec, chess, kindResult))
    {
        return SessionAction::ACTION_CHI;
    }

    return SessionAction::ACTION_DISPATH;
}

bool SessionController::checkOutputChessChi(Postion currentPs, Postion outputPs, const std::vector<Chess>& chessVec, const Chess& chess, std::vector<KindChess>& kindResult)
{
    if (Utils::getNextDispatchPostion(outputPs) != currentPs)
    {
        return false;
    }

    kindResult.clear();
    auto iterFindlow2 = std::find(chessVec.begin(), chessVec.end(), Chess(chess.type, chess.count - 2));
    auto iterFindlow1 = std::find(chessVec.begin(), chessVec.end(), Chess(chess.type, chess.count - 1));
    auto iterFindhigh1 = std::find(chessVec.begin(), chessVec.end(), Chess(chess.type, chess.count + 1));
    auto iterFindhigh2 = std::find(chessVec.begin(), chessVec.end(), Chess(chess.type, chess.count + 2));

    if ((iterFindlow2 != chessVec.end()) &&
        (iterFindlow1 != chessVec.end()))
    {
        KindChess weaveChess;
        weaveChess.type = ChessStatus::CHI;
        weaveChess.item.push_back(Chess(*iterFindlow2));
        weaveChess.item.push_back(Chess(*iterFindlow1));
        weaveChess.item.push_back(chess);
        kindResult.push_back(weaveChess);
    }

    if ((iterFindlow1 != chessVec.end()) &&
        (iterFindhigh1 != chessVec.end()))
    {
        KindChess weaveChess;
        weaveChess.type = ChessStatus::CHI;
        weaveChess.item.push_back(Chess(*iterFindlow1));
        weaveChess.item.push_back(chess);
        weaveChess.item.push_back(Chess(*iterFindhigh1));
        kindResult.push_back(weaveChess);
    }

    if ((iterFindhigh1 != chessVec.end()) &&
        (iterFindhigh2 != chessVec.end()))
    {
        KindChess weaveChess;
        weaveChess.type = ChessStatus::CHI;
        weaveChess.item.push_back(chess);
        weaveChess.item.push_back(Chess(*iterFindhigh1));
        weaveChess.item.push_back(Chess(*iterFindhigh2));
        kindResult.push_back(weaveChess);
    }
    return (!kindResult.empty());
}

bool SessionController::checkOutputChessPeng(const std::vector<Chess>& chessVec, const Chess& chess, std::vector<KindChess>& kindResult)
{
    KindChess weaveChess;
    weaveChess.type = ChessStatus::PENG;
    for (size_t i = 0; i < chessVec.size(); i++)
    {
        if (chessVec.at(i) == chess)
        {
            weaveChess.item.push_back(chessVec.at(i));
        }
    }
    if (weaveChess.item.size() >= 2)
    {
        weaveChess.item.push_back(chess);
        kindResult.push_back(weaveChess);
        return true;
    }
    return false;
}

bool SessionController::checkOutputChessGang(const std::vector<Chess>& chessVec, const Chess& chess, std::vector<KindChess>& kindResult)
{
    KindChess weaveChess;
    weaveChess.type = ChessStatus::GANG;
    for (size_t i = 0; i < chessVec.size(); i++)
    {
        if (chessVec.at(i) == chess)
        {
            weaveChess.item.push_back(chessVec.at(i));
        }
    }
    if (weaveChess.item.size() >= 3)
    {
        weaveChess.item.push_back(chess);
        kindResult.push_back(weaveChess);
        return true;
    }
    return false;
}

bool SessionController::checkOutputChessHu(const std::vector<Chess>& chessVec, const Chess& chess, std::vector<KindChess>& kindResult)
{
    CheckWin checkWind(chessVec, chess);
    return checkWind.analyseChess2Win(kindResult);
}

SitPostion SessionController::getSitPostionByPs(Postion ps)
{
    auto mainUse = m_model->getUserPlayerPs();
    return Utils::getPlayerSitPostion(mainUse.postion, ps);
}
